package com.mc.lp.core.util.property;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;

import javax.annotation.Resource;
import javax.transaction.Transactional;

import org.springframework.util.CollectionUtils;

import com.mc.lp.database.dao.impl.DBPropertyDAOImpl;
import com.mc.lp.database.dao.impl.EnvDAOImpl;
import com.mc.lp.shared.vo.KeyValue;

/**
 * this class will return the db properties stored in database as well as file system, this class is being made to avoid the headache to keep properties files and spending
 * alot time to manage them.
 * @author deepak
 *
 */
public class PropertyUtil implements IPropertyUtil {
	@Resource
	private EnvDAOImpl environmentDao;
	@Resource
	private DBPropertyDAOImpl dbPropertyDao;
	private String env;
	private PropertyContainer propertyContainer = new PropertyContainer();
	
	@Transactional
	public void loadProperties() throws IOException {
		env=getEnvironmentDao().getEnvironment();
		//loop each property file and load the properties
		for(PropertyFile file: PropertyFile.values()){
			if(file.getType().equals(PropertyFile.PropertyFileType.DATABASE)){
				//load property from database
				loadPropertiesFromDatabase(file);
			}
			if(file.getType().equals(PropertyFile.PropertyFileType.FILE_SYSTEM)){
				//load properties from file system
				loadPropertiesFromFileSystem(file);
			}
		}
	}
	
	/**
	 * return the value of the given property, it will search the property in the given property file (either loaded from file system or database)
	 * @author deepak
	 */
	@Transactional
	public String getProperty(String propertyName, PropertyFile propertyFileName) {
		if(getPropertyContainer()!=null && !CollectionUtils.isEmpty(getPropertyContainer().getPropertyMap())){
				Properties properties=getPropertyContainer().getPropertyMap().get(propertyFileName);
				if(properties!=null && !properties.isEmpty()){
					return String.valueOf(properties.get(propertyName));
				}
		}
		throw new NullPointerException("No Such property exists. name="+propertyName + ", file/module :"+propertyFileName);
	}
	
	/**
	 * loading properties into property container
	 * @param propertyFile
	 */
	private void loadPropertiesFromDatabase(PropertyFile propertyFile){
		List<KeyValue> propertyList= getDbPropertyDao().getAllPropertiesByEnvAndModule(this.env, propertyFile.toString());
		Properties properties = new Properties();
		if(!CollectionUtils.isEmpty(propertyList)){
			for(KeyValue keyValue:propertyList){
				properties.put(keyValue.getKey(), keyValue.getValue());		
			}
			getPropertyContainer().getPropertyMap().put(propertyFile, properties);
		}
	}
	
	/**
	 * loading the properties from file system
	 * @param propertyFile
	 * @throws IOException 
	 */
	private void loadPropertiesFromFileSystem(PropertyFile propertyFile) throws IOException{
		String fileName=resolveFileName(propertyFile);
		Properties prop = new Properties();
		InputStream input = null;
		try {
			input = getClass().getClassLoader().getResourceAsStream(fileName);
			System.out.println("file name: "+fileName);
			if (input == null) {
				throw new NullPointerException("unable to find property file" + fileName);
			}
			prop.load(input);
			//load properties into property map
			getPropertyContainer().getPropertyMap().put(propertyFile, prop);
		} catch (IOException ex) {
			ex.printStackTrace();
		} finally {
			if (input != null) {
				try {
					input.close();
				} catch (IOException e) {
					throw e;
				}
			}
		}
	}
	
	/**
	 * resolve the file name based on environment available in database.
	 * @param propertyFile
	 * @return
	 */
	private String resolveFileName(PropertyFile propertyFile){
		if(propertyFile.getType().equals(PropertyFile.PropertyFileType.FILE_SYSTEM)){
			String uri=propertyFile.getUri();
			StringBuilder newFileName= new StringBuilder(uri.substring(0,uri.indexOf(".properties")));
			newFileName.append("_");
			newFileName.append((this.env).toLowerCase());
			newFileName.append(".properties");
			return newFileName.toString();
		}
		throw new NullPointerException("Argument not valid, property file type should be of FILE_SYSTEM only");
	}
	
	public void refreshProperties() {
	}
	public EnvDAOImpl getEnvironmentDao() {
		return environmentDao;
	}

	public void setEnvironmentDao(EnvDAOImpl environmentDao) {
		this.environmentDao = environmentDao;
	}

	public DBPropertyDAOImpl getDbPropertyDao() {
		return dbPropertyDao;
	}

	public void setDbPropertyDao(DBPropertyDAOImpl dbPropertyDao) {
		this.dbPropertyDao = dbPropertyDao;
	}

	public PropertyContainer getPropertyContainer() {
		return propertyContainer;
	}

	public void setPropertyContainer(PropertyContainer propertyContainer) {
		this.propertyContainer = propertyContainer;
	}

	public String getEnv() {
		return env;
	}

	public void setEnv(String env) {
		this.env = env;
	}
}